package com.googlecode.perfectable.prosperable.webchat;

import javax.annotation.Nullable;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import com.googlecode.perfectable.eventable.routing.DispatchingSink;
import com.googlecode.perfectable.eventable.routing.DispatchingSink.MissedTypeStrategy;
import com.googlecode.perfectable.eventable.routing.Sink;
import com.googlecode.perfectable.eventable.routing.Source;
import com.googlecode.perfectable.prosperable.entry.ChannelManager;
import com.googlecode.perfectable.prosperable.message.ClientMessage;
import com.googlecode.perfectable.prosperable.message.ServerMessage;
import com.googlecode.perfectable.prosperable.webchat.message.LogCreatedMessage;
import com.googlecode.perfectable.prosperable.webchat.message.LogPublishedMessage;
import com.googlecode.perfectable.webchat.ChatService;
import com.googlecode.perfectable.webchat.MemoryChatService;
import com.googlecode.perfectable.webchat.Message;

public class ServiceConfiguratorListener implements HttpSessionListener {
	private static final ChatService CHAT_SERVICE = new MemoryChatService();
	
	@Override
	public void sessionCreated(@Nullable HttpSessionEvent se) {
		if(se == null) {
			throw new RuntimeException();
		}
		final HttpSession session = se.getSession();
		Source<ClientMessage> inbound = ChannelManager.extractInbound(session);
		Sink<ServerMessage> outbound = ChannelManager.extractOutbound(session);
		configure(inbound, outbound);
	}

	@Override
	public void sessionDestroyed(@Nullable HttpSessionEvent se) {
		if(se == null) {
			throw new RuntimeException();
		}
		// MARK close?
	}
	
	private void configure(Source<ClientMessage> inbound, Sink<ServerMessage> outbound) {
		Sink<ClientMessage> clientMessageSink = DispatchingSink.<ClientMessage> create(MissedTypeStrategy.THROWING)
				.dispatch(LogCreatedMessage.class, new Sink<LogCreatedMessage>() {
					@Override
					public void receive(LogCreatedMessage event) {
						event.pushInto(CHAT_SERVICE);
					}
				});
		inbound.listen(clientMessageSink);

		Sink<Message> serverMessageSink = new Sink<Message>() {
			@Override
			public void receive(Message event) {
				outbound.receive(LogPublishedMessage.create(event));
			}
		};
		CHAT_SERVICE.listen(serverMessageSink);
	}
	
}
